home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
drdobbs
/
1992
/
04
/
386bsd.492
next >
Wrap
Text File
|
1992-03-18
|
7KB
|
247 lines
_PORTING UNIX TO THE 386_
by William Frederick Jolitz and Lynne Greer Jolitz
[LISTING ONE]
/* [Excerpted from /sys/i386/isa/icu.h] */
...
/* Macro's for interrupt level priority masks (used in assembly code) */
/* mask additional interrupts */
#define ORPL(m) \
cli ; /* disable interrupts */ \
movw m , %dx ; /* get the mask */ \
inb $ IO_ICU1+1, %al ; /* next, get low order mask */ \
xchgb %dl, %al ; /* switch the old with the new */ \
orb %dl, %al ; /* finally, or it in! */ \
outb %al, $ IO_ICU1+1 ; \
inb $0x84, %al ; \
inb $ IO_ICU2+1, %al ; /* next, get high order mask */ \
xchgb %dh, %al ; /* switch the old with the new */ \
orb %dh, %al ; /* finally, or it in! */ \
outb %al, $ IO_ICU2+1 ; \
inb $0x84, %al ; /* flush write buffer, delay bus cycle */ \
movzwl %dx, %eax ; /* return old priority */ \
sti ; /* enable interrupts */
/* force interrupt mask */
#define SETPL(v) \
cli ; /* disable interrupts */ \
movw v , %dx ; \
inb $ IO_ICU1+1, %al ; /* next, get low order mask */ \
xchgb %dl, %al ; /* switch the old with the new */ \
outb %al, $ IO_ICU1+1 ; \
inb $0x84, %al ; \
inb $ IO_ICU2+1, %al ; /* next, get high order mask */ \
xchgb %dh, %al ; /* switch the copy with the new */ \
outb %al, $ IO_ICU2+1 ; \
inb $0x84, %al ; /* flush write buffer, delay bus cycle */ \
movzwl %dx, %eax ; /* return old priority */ \
sti ; /* enable interrupts */
/* Mask a group of interrupts atomically - interrupt entry */
#define INTR(unit,mask,offst) \
pushl $0 ; /* first, build a trap frame for ... */ \
pushl $ T_ASTFLT ; /* ... possible rescheduling that may occur */ \
pushal ; \
nop ; \
movb $0x20, %al ; /* next, as soon as possible send EOI ... */ \
outb %al, $ IO_ICU1 ; /* ...so in service bit may be cleared ...*/ \
inb $0x84, %al ; /* ... ASAP */ \
movb $0x20, %al ; /* likewise, the other one as well */ \
outb %al,$ IO_ICU2 ; \
inb $0x84,%al ; \
pushl %ds ; /* save our data and extra segments ... */ \
pushl %es ; \
movw $0x10, %ax ; /* ... and reload with kernel's own */ \
movw %ax, %ds ; \
movw %ax, %es ; \
incl _cnt+V_INTR ; /* tally interrupts */ \
incl _isa_intr + offst * 4 ; \
movw mask , %dx ; /* assert group mask */ \
inb $ IO_ICU1+1, %al ; /* next, get low order mask */ \
xchgb %dl, %al ; /* switch the old with the new */ \
orb %dl, %al ; /* finally, or it in! */ \
outb %al, $ IO_ICU1+1 ; \
inb $0x84,%al ; \
inb $ IO_ICU2+1, %al ; /* next, get high order mask */ \
xchgb %dh, %al ; /* switch the old with the new */ \
orb %dh, %al ; /* finally, or it in! */ \
outb %al, $ IO_ICU2+1 ; \
inb $0x84, %al ; \
pushl %edx ; /* save old mask for when we return */ \
pushl $ unit ; /* finish off interrupt frame with unit # */ \
sti ; /* and allow other unmasked interrupts */
...
[LISTING TWO]
/* AT/386 -- Interrupt vector routines -- Generated by config program */
#include "machine/isa/isa.h"
#include "machine/isa/icu.h"
#define VEC(name) .align 4; .globl _V/**/name; _V/**/name:
.globl _hardclock
VEC(clk)
INTR(0, ___highmask__, 0)
call _hardclock
INTREXIT1
.globl _wdintr, _wd0mask
.data
_wd0mask: .long 0
.text
VEC(wd0)
INTR(0, ___biomask__, 1)
call _wdintr
INTREXIT2
.globl _fdintr, _fd0mask
.data
_fd0mask: .long 0
.text
VEC(fd0)
INTR(0, ___biomask__, 2)
call _fdintr
INTREXIT1
.globl _cnrint, _cn0mask
.data
_cn0mask: .long 0
.text
VEC(cn0)
INTR(0, ___ttymask__, 3)
call _cnrint
INTREXIT1
.globl _npxintr, _npx0mask
.data
_npx0mask: .long 0
.text
VEC(npx0)
INTR(0, _npx0mask, 4)
call _npxintr
INTREXIT2
.globl _comintr, _com0mask
.data
_com0mask: .long 0
.text
VEC(com0)
INTR(0, ___ttymask__, 5)
call _comintr
INTREXIT1
.globl _weintr, _we0mask
.data
_we0mask: .long 0
.text
VEC(we0)
INTR(0, ___netmask__, 6)
call _weintr
INTREXIT1
.globl _lptintr, _lpt0mask
.data
_lpt0mask: .long 0
.text
VEC(lpt0)
INTR(0, ___ttymask__, 7)
call _lptintr
INTREXIT1
[LISTING THREE]
/* [Excerpted from /sys/i386/isa/icu.h] */
...
/* First eight interrupts (ICU1) */
#define INTREXIT1 \
jmp doreti
/* Second eight interrupts (ICU2) */
#define INTREXIT2 \
jmp doreti
...
/* [Excerpted from /sys/i386/isa/icu.s] */
...
/* Handle return from interrupt after device handler finishes */
doreti:
/* move to a trap frame */
cli /* interrupts off while we work ... */
popl %ebx /* remove unit number */
popl %eax /* get previous priority mask */
/* restore previous mask */
movw %ax, %cx
outb %al, $ IO_ICU1+1
inb $0x84, %al
movb %ah, %al
outb %al, $ IO_ICU2+1
inb $0x84, %al
/* are we at interrupt level / nested interrupt already ? */
cmpw ___nonemask__, %cx
jne 3f
/* do we need to process an network software interrupt ? */
cmpl $0, _netisr
je 2f
btsl $ NETISR_PROCESS, _netisr
jb 2f
#include "../net/netisr.h"
#define DOCALL(n, s, c) ; \
.globl c ; \
btrl $ s , n ; \
jnb 1f ; \
call c ; \
1:
/* process a network software interrupt */
sti
DOCALL(_netisr, NETISR_RAW, _rawintr)
#ifdef INET
DOCALL(_netisr, NETISR_IP, _ipintr)
#endif
#ifdef IMP
DOCALL(_netisr, NETISR_IMP, _impintr)
#endif
#ifdef NS
DOCALL(_netisr, NETISR_NS, _nsintr)
#endif
btrl $ NETISR_PROCESS, _netisr
2:
/* do we need to process a software clock "interrupt" */
cli
btrl $ SCLK_NEED, ___softclock__
jnb 1f
btsl $ SCLK_PROCESS, ___softclock__
jb 1f
/* process a software clock "interrupt" */
sti
pushl ___nonemask__ /* to an interrupt frame again */
pushl %ebx
call _softclock
popl %eax /* back to trap frame for possible AST */
popl %eax
btrl $ SCLK_PROCESS, ___softclock__
1:
/* see if we need to process an AST (rescheduling) fault */
cmpw $0x1f, tCS*4(%esp) /* were we executing from a user mode ... */
jne 3f /* ... code selector? */
DOCALL(___ast__, AST_NEED, _trap);
3:
/* restore the state and return */
popl %es
popl %ds
popal
nop
addl $8, %esp
iret
...